package com.lxq.particledemo02;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import android.content.res.Resources;
import android.opengl.GLES20;
import android.util.Log;

/*
 * ����������������ض�����ɫ����ƬԪ��ɫ��
 */
public class ShaderUtil {

	/**
	 * ������ɫ������
	 *
	 * ���� :
	 *
	 * �� ������ɫ��
	 * �� ������ɫ���ű�
	 * �� ������ɫ��
	 * �� ��ȡ��ɫ��������
	 *
	 * @param shaderType ��ɫ������,������ɫ��(GLES20.GL_FRAGMENT_SHADER), ƬԪ��ɫ��(GLES20.GL_FRAGMENT_SHADER)
	 * @param source ��ɫ�ű��ַ���
	 * @return ���ص�����ɫ��������, ����ֵ���Դ�����ص���ɫ��
	 */
	public static int loadShader(int shaderType , String source){
		//1.����һ����ɫ��, ����¼����������ɫ����id, ���id==0, ��ô����ʧ��
		int shader = GLES20.glCreateShader(shaderType);
		if(shader != 0){
			//2.�����ɫ�������ɹ�, Ϊ��������ɫ�����ؽű�����
			GLES20.glShaderSource(shader, source);
			//3.�����Ѿ����ؽű��������ɫ��
			GLES20.glCompileShader(shader);
			checkGLError("glCompileShader");
			int[] compiled = new int[1];
			//4.��ȡ��ɫ���ı������, ������Ϊ0, ˵������ʧ��
			GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
			if(compiled[0] == 0){
				Log.e("ES20_ERROR", "Could not compile shader " + shaderType + ":");
				Log.e("ES20_ERROR", "ERROR: "+GLES20.glGetShaderInfoLog(shader));
				//����ʧ�ܵĻ�, ɾ����ɫ��, ����ʾlog
				GLES20.glDeleteShader(shader);
				shader = 0;
			}
		}
		else{
			Log.e("ES20_ERROR", "Could not Create shader " + shaderType + ":"+
					"Error:"+ shader);
		}
		return shader;
	}

	/**
	 * ���ÿһ���Ĳ����Ƿ���ȷ
	 *
	 * ʹ��GLES20.glGetError()�������Ի�ȡ�������, ����������Ϊ0, ��ô��û�д���
	 *
	 * @param op ����ִ�еķ�����, ����ִ������ɫ�����м�����ɫ��,
	 * 		ʹglAttachShader()����, ��ô�����������"glAttachShader"
	 */
	public static void checkGLError(String op){
		int error;
		//������벻Ϊ0, �ʹ�ӡ������־, ���׳��쳣
		while( (error = GLES20.glGetError()) != GLES20.GL_NO_ERROR ){
			Log.e("ES20_ERROR", op + ": glError " + error);
			throw new RuntimeException(op + ": glError " + error);
		}
	}

	/**
	 * ������ɫ����
	 *
	 * �� ���ض�����ɫ��
	 * �� ����ƬԪ��ɫ��
	 * �� ������ɫ����
	 * �� ����ɫ�����м��붥����ɫ��
	 * �� ����ɫ�����м���ƬԪ��ɫ��
	 * �� ���ӳ���
	 * �� ��ȡ���ӳ�����
	 *
	 * @param vertexSource		������ɫ���ű��ַ���
	 * @param fragmentSource	ƬԪ��ɫ���ű��ַ���
	 * @return
	 */
	public static int createProgram(String vertexSource , String fragmentSource){
		//1. ���ض�����ɫ��, ����0˵������ʧ��
		int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
		if(vertexShader == 0)
		{
			Log.e("ES20_ERROR", "���ض�����ɫ��ʧ��");
			return 0;
		}
		//2. ����ƬԪ��ɫ��, ����0˵������ʧ��
		int fragShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
		if(fragShader == 0)
		{
			Log.e("ES20_ERROR", "����ƬԪ��ɫ��ʧ��");
			return 0;
		}
		//3. ������ɫ����, ����0˵������ʧ��
		int program = GLES20.glCreateProgram();
		if(program != 0){
			//4. ����ɫ�����м��붥����ɫ��
			GLES20.glAttachShader(program, vertexShader);
			//���glAttachShader������û��ʧ��
			checkGLError("glAttachShader");
			//5. ����ɫ�����м���ƬԪ��ɫ��
			GLES20.glAttachShader(program, fragShader);
			//���glAttachShader������û��ʧ��
			checkGLError("glAttachShader");

			//6. ���ӳ���
			GLES20.glLinkProgram(program);
			int[] linkStatus = new int[1];
			//��ȡ���ӳ�����
			GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
			if(linkStatus[0] != GLES20.GL_TRUE){
				Log.e("ES20.ERROR", "���ӳ���ʧ�� : ");
				Log.e("ES20.ERROR", GLES20.glGetProgramInfoLog(program));
				//������ӳ���ʧ��ɾ������
				GLES20.glDeleteProgram(program);
				program = 0;
			}
		}
		else{
			Log.e("ES20_ERROR", "glCreateProgram Failed: "+program);
		}

		return program;
	}

	/**
	 * ��assets�м�����ɫ�ű�
	 *
	 * �� ��assetsĿ¼�е��ļ�������
	 * �� �������������������
	 * �� ����ֽڶ�ȡ�ļ�����, ���뻺����
	 * �� ���������е�����תΪ�ַ���
	 *
	 * @param fileName assetsĿ¼�е���ɫ�ű��ļ���
	 * @param resources	Ӧ�õ���Դ
	 * @return
	 */
	public static String loadFromAssetsFile(String fileName, Resources resources){
		String result = null;
		try {
			//1. ��assetsĿ¼�ж�ȡ�ļ���������, �൱�ڴ�����һ���ļ����ֽ�������
			InputStream is = resources.getAssets().open(fileName);
			int ch = 0;
			//2. ����һ�����������������, ÿ�ζ�ȡһ���ֽ�, ע�������ֽڶ�ȡ�õ���int����
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			//3. ����ֽڶ�ȡ����, ������ȡ�����ݷ��뻺������
			while((ch = is.read()) != -1){
				baos.write(ch);
			}
			//4. ���������е�����תΪ�ֽ�����, �����ֽ�����ת��Ϊ�ַ���
			byte[] buffer = baos.toByteArray();
			baos.close();
			is.close();
			result = new String(buffer, "UTF-8");
			result = result.replaceAll("\\r\\n", "\n");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

}
